from typing import List, Optional
from sqlalchemy.orm import Session
from sqlalchemy import or_
from fastapi import HTTPException, status

from app.models.user import User
from app.models.role import Role
from app.models.user_role import UserRole
from app.schemas.user import UserCreate, UserUpdate
from app.core.logging import get_logger

logger = get_logger(__name__)


class UserService:
    """用户服务类"""
    
    def __init__(self, db: Session):
        self.db = db
    
    def calculate_profile_completion(self, user: User) -> int:
        """计算用户资料完整度"""
        # 定义需要检查的字段
        fields_to_check = [
            'email',
            'phone',
            'full_name',
            'avatar'
        ]
        
        # 添加调试信息
        logger.debug(f"计算用户 {user.id} 的资料完整度")
        logger.debug(f"用户数据: {vars(user)}")
        
        # 过滤出非空且非空字符串的字段
        filled_fields = [
            field for field in fields_to_check 
            if getattr(user, field, None) is not None and getattr(user, field, None) != ''
        ]
        
        logger.debug(f"需要检查的字段: {fields_to_check}")
        logger.debug(f"已填写的字段: {filled_fields}")
        
        # 计算完成度百分比
        completion = round((len(filled_fields) / len(fields_to_check)) * 100) if fields_to_check else 0
        logger.debug(f"计算出的完整度: {completion}%")
        return completion
    
    def get_by_id(self, user_id: int) -> Optional[User]:
        """根据ID获取用户"""
        return self.db.query(User).filter(User.id == user_id).first()
    
    def get_by_username(self, username: str) -> Optional[User]:
        """根据用户名获取用户"""
        return self.db.query(User).filter(User.username == username).first()
    
    def get_by_email(self, email: str) -> Optional[User]:
        """根据邮箱获取用户"""
        return self.db.query(User).filter(User.email == email).first()
    
    def get_all(self, skip: int = 0, limit: int = 100, is_active: Optional[bool] = None) -> List[User]:
        """获取所有用户"""
        query = self.db.query(User)
        if is_active is not None:
            query = query.filter(User.is_active == is_active)
        return query.offset(skip).limit(limit).all()
    
    def search_users(self, keyword: str, skip: int = 0, limit: int = 100) -> List[User]:
        """搜索用户"""
        return self.db.query(User).filter(
            or_(
                User.username.contains(keyword),
                User.full_name.contains(keyword),
                User.email.contains(keyword)
            )
        ).offset(skip).limit(limit).all()

    def get_users(self, skip: int = 0, limit: int = 100, search: Optional[str] = None, is_active: Optional[bool] = None) -> tuple[List[User], int]:
        """获取用户列表，支持搜索和筛选"""
        query = self.db.query(User)
        
        # 应用搜索条件
        if search:
            query = query.filter(
                or_(
                    User.username.contains(search),
                    User.full_name.contains(search),
                    User.email.contains(search)
                )
            )
        
        # 应用激活状态筛选
        if is_active is not None:
            query = query.filter(User.is_active == is_active)
        
        # 获取总数
        total = query.count()
        
        # 获取分页数据
        users = query.offset(skip).limit(limit).all()
        
        return users, total
    
    def create_user(self, user_data: UserCreate) -> User:
        """创建用户"""
        # 检查用户名是否已存在
        if self.get_by_username(user_data.username):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="用户名已存在"
            )
        
        # 检查邮箱是否已存在
        if self.get_by_email(user_data.email):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="邮箱已存在"
            )
        
        # 创建用户
        # 注意：避免在服务内部导入其他服务，改为使用传入的auth_service或直接创建
        from app.services.auth_service import AuthService
        auth_service = AuthService(self.db)
        try:
            hashed_password = auth_service.get_password_hash_with_policy(
                user_data.password, 
                user_data.username, 
                user_data.email
            )
        except HTTPException:
            # 重新抛出密码策略相关的异常
            raise
        except Exception as e:
            logger.error(f"密码哈希生成失败: {e}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="用户创建失败：密码处理错误"
            )
        
        db_user = User(
            email=user_data.email,
            username=user_data.username,
            full_name=user_data.full_name,
            phone=user_data.phone,
            avatar=user_data.avatar,
            hashed_password=hashed_password,
            is_active=user_data.is_active,
            is_verified=user_data.is_verified
        )
        
        self.db.add(db_user)
        self.db.commit()
        self.db.refresh(db_user)
        
        # 分配角色
        if user_data.role_ids:
            # 直接使用db_user.id，让assign_roles处理类型转换
            self.assign_roles(int(str(db_user.id)), user_data.role_ids)
            self.db.refresh(db_user)
        
        return db_user
    
    def update_user(self, user_id: int, user_data: UserUpdate) -> User:
        """更新用户"""
        user = self.get_by_id(user_id)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 检查用户名是否被占用
        if user_data.username and user_data.username != user.username:
            existing_user = self.get_by_username(user_data.username)
            if existing_user:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="用户名已存在"
                )
        
        # 检查邮箱是否被占用
        if user_data.email and user_data.email != user.email:
            existing_user = self.get_by_email(user_data.email)
            if existing_user:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail="邮箱已存在"
                )
        
        # 更新用户字段
        update_data = user_data.dict(exclude_unset=True)
        for field, value in update_data.items():
            if field != "role_ids":
                setattr(user, field, value)
        
        self.db.commit()
        self.db.refresh(user)
        
        # 更新角色
        if "role_ids" in update_data:
            self.assign_roles(int(str(user_id)), update_data["role_ids"])
            self.db.refresh(user)
        
        return user
    
    def delete_user(self, user_id: int) -> bool:
        """删除用户"""
        user = self.get_by_id(user_id)
        if not user:
            return False
        
        self.db.delete(user)
        self.db.commit()
        return True
    
    def assign_roles(self, user_id: int, role_ids: List[int]) -> None:
        """分配角色给用户"""
        user = self.get_by_id(user_id)
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 移除现有角色关联
        self.db.query(UserRole).filter(UserRole.user_id == user_id).delete()
        
        # 添加新的角色关联
        for role_id in role_ids:
            role = self.db.query(Role).filter(Role.id == role_id).first()
            # 使用显式布尔检查避免类型问题
            if role:
                # 先获取role.is_active的值
                is_active_value = role.is_active
                # 尝试转换为布尔值
                try:
                    is_active_bool = bool(is_active_value)
                except:
                    # 如果转换失败，默认为False
                    is_active_bool = False
                    
                if is_active_bool:
                    user_role = UserRole(
                        user_id=user_id,
                        role_id=role_id,
                        is_active=True
                    )
                    self.db.add(user_role)
        
        self.db.commit()
    
    def get_user_roles(self, user_id: int) -> List[Role]:
        """获取用户的所有角色"""
        user = self.get_by_id(user_id)
        if not user:
            return []
        # 使用显式布尔检查避免类型问题
        result = []
        for role in user.roles:
            # 先获取role.is_active的值
            is_active_value = role.is_active
            # 尝试转换为布尔值
            try:
                is_active_bool = bool(is_active_value)
            except:
                # 如果转换失败，默认为False
                is_active_bool = False
                
            if is_active_bool:
                result.append(role)
        return result
    
    def get_user_permissions(self, user_id: int) -> List[str]:
        """获取用户的所有权限"""
        user = self.get_by_id(user_id)
        if not user:
            return []
        return list(user.get_all_permissions())
    
    def has_permission(self, user_id: int, permission: str) -> bool:
        """检查用户是否有特定权限"""
        user = self.get_by_id(user_id)
        if not user:
            return False
        return user.has_permission(permission)
    
    def has_role(self, user_id: int, role_name: str) -> bool:
        """检查用户是否有特定角色"""
        user = self.get_by_id(user_id)
        if not user:
            return False
        return user.has_role(role_name)

    def get_user(self, user_id: int) -> Optional[User]:
        """获取单个用户信息（兼容API调用）"""
        user = self.get_by_id(user_id)
        if user:
            # 动态添加 profile_completion 属性
            completion = self.calculate_profile_completion(user)
            user.profile_completion = completion
            logger.debug(f"User {user_id} profile completion: {completion}")  # 添加调试日志
        return user

    def activate_user(self, user_id: int) -> Optional[User]:
        """激活用户"""
        user = self.get_by_id(user_id)
        if not user:
            return None
        
        # 使用setattr避免类型检查问题
        setattr(user, 'is_active', True)
        self.db.commit()
        self.db.refresh(user)
        return user

    def deactivate_user(self, user_id: int) -> Optional[User]:
        """停用用户"""
        user = self.get_by_id(user_id)
        if not user:
            return None
        
        # 使用setattr避免类型检查问题
        setattr(user, 'is_active', False)
        self.db.commit()
        self.db.refresh(user)
        return user